package com.sunday.framework.fegin;

import com.sunday.common.core.constants.LogConstants;
import com.sunday.common.core.enums.ErrorCodeEnum;
import com.sunday.common.core.exception.BusinessException;
import com.sunday.common.core.gson.GsonUtils;
import com.sunday.common.core.remoting.base.auth.CurrentUser;
import com.sunday.common.core.remoting.rest.annotation.OpenApi;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import java.util.Optional;

/**
 * @Description: 当前用户持有者
 * @Author: zsy
 */
@Slf4j
public class CurrentUserHolder {

    private static final ThreadLocal<CurrentUser> contextHolder = new ThreadLocal<>();

    /**
     * @Description: 通过 请求头中的 tokenInfo 绑定当前登录人信息
     * @Param: [openApi 为null时，则默认进行绑定动作 ]111
     * @Return: void
     */
    public static void bind(OpenApi openApi) {
        //每次绑定之前优先进行解绑
        unbind();
        //接口是否公开，null 不公开，必须验证用户信息
        if (openApi == null) {
            contextHolder.set(
                    Optional.ofNullable(RequestContextHolder.getRequestAttributes())
                            .filter(requestAttributes -> requestAttributes instanceof ServletRequestAttributes)
                            .map(requestAttributes -> ServletRequestAttributes.class.cast(requestAttributes)
                                    .getRequest()
                                    .getHeader(CurrentUser.HTTP_HEADER_AUTH_TOKEN_INFO))
                            .filter(tokenInfo -> StringUtils.hasText(tokenInfo))
                            .map(tokenInfo -> GsonUtils.DEFAULT.fromJson(tokenInfo, CurrentUser.class))
                            /** A0_200(ErrorClassifyEnum.A + "0200","用户登录异常") **/
                            .orElseThrow(() -> new BusinessException(ErrorCodeEnum.A0_200))
            );
            log.info(LogConstants.bind_format, contextHolder.get());
        }
    }

    /**
     * @Description: 获取当前登录人信息， 如果获取不到返回异常
     * @Param: []
     * @Return: com.sunday.common.core.remoting.base.auth.CurrentUser
     */
    public static CurrentUser getUser() {
        return Optional.ofNullable(contextHolder.get())
                /** A0_200(ErrorClassifyEnum.A + "0200","用户登录异常") **/
                .orElseThrow(() -> new BusinessException(ErrorCodeEnum.A0_200));
    }

    /**
     * @Description: 解除绑定
     * @Param: []
     * @Return: void
     */
    public static void unbind() {
        contextHolder.remove();
    }

}
